//Nathan Popham
//4003-573-01: Procedural Shading
//Lab 4 
//
//mybrick.frag
// Textures a surface with a pattern of 1x1, 1x2, and 2x2 blocks. A predefined
// 5x5 pattern of these blocks is repeated across the surface. The surface is
// bumpmapped over a noise function. The surface color is also varied according
// to a noise function.
//

varying vec3 P;
varying vec3 N;
varying vec3 T;
varying vec3 B;
varying vec3 LightDir;
varying vec3 EyeDir;


float turbulence(vec2 p, int octaves, float lacunarity, float gain)
{
    float sum = 0.0, amp = 1.0; 
    vec2 pp = p; 
    int i; 
 
    for(i = 0; i < octaves; i += 1) 
    { 
        sum += amp * abs(2.0*noise1(pp)-1.0); 
        amp *= gain; pp *= lacunarity; 
    } 
    return sum; 
} 


int TwoDIndex(float x, float y, float width) { return int(x + y * width); }

float sqr(float x) { return x * x; }

void main()
{
    //unfortunately have to hardcode the array
    //glsL doesn't seem to have inline array initialization
    //(actually our grad has just told me there IS, but these are done)
    //a 3.0 represents a tile with top and left mortar border
    //a 2.0 is a tile with only top mortar border
    //a 1.0 is a tile with only left mortar border
    //a 0.0 is a tile with no mortar borders
    float brickPattern[25];
    brickPattern[0] = 3.0;
    brickPattern[1] = 2.0;
    brickPattern[2] = 3.0;
    brickPattern[3] = 3.0;
    brickPattern[4] = 2.0;
    brickPattern[5] = 3.0;
    brickPattern[6] = 3.0;
    brickPattern[7] = 1.0;
    brickPattern[8] = 3.0;
    brickPattern[9] = 2.0;
    brickPattern[10] = 1.0;
    brickPattern[11] = 3.0;
    brickPattern[12] = 2.0;
    brickPattern[13] = 3.0;
    brickPattern[14] = 3.0;
    brickPattern[15] = 3.0;
    brickPattern[16] = 2.0;
    brickPattern[17] = 3.0;
    brickPattern[18] = 1.0;
    brickPattern[19] = 3.0;
    brickPattern[20] = 1.0;
    brickPattern[21] = 0.0;
    brickPattern[22] = 3.0;
    brickPattern[23] = 2.0;
    brickPattern[24] = 1.0;

    vec3 bc1 = vec3(.5, .5, .8);
    vec3 bc2 = vec3(.8, .5, .5);
    vec3 bc3 = vec3(.5, .8, .5);
    int brickColors[25];
    brickColors[0] = 1;
    brickColors[1] = 1;
    brickColors[2] = 2;
    brickColors[3] = 3;
    brickColors[4] = 3;
    brickColors[5] = 2;
    brickColors[6] = 3;
    brickColors[7] = 2;
    brickColors[8] = 1;
    brickColors[9] = 1;
    brickColors[10] = 2;
    brickColors[11] = 1;
    brickColors[12] = 1;
    brickColors[13] = 3;
    brickColors[14] = 2;
    brickColors[15] = 1;
    brickColors[16] = 1;
    brickColors[17] = 2;
    brickColors[18] = 3;
    brickColors[19] = 2;
    brickColors[20] = 1;
    brickColors[21] = 1;
    brickColors[22] = 3;
    brickColors[23] = 3;
    brickColors[24] = 2;

    float SpecularFactor = .5;
    float tilewidth = 2.0;
    float tileheight = 2.0;
    float mortarwidth = 0.2;
    vec3 mortarcolor = vec3 (0.4, 0.4, 0.4);
    vec3 brickcolor = vec3(0.5, 0.5, 0.8);
    float lacunity = 2.0;
    float gain = 0.8;
    float groovedepth = .5; 

    float numTilesWidth = 5.0;
    float numTilesHeight = 5.0;
    
    float is = gl_TexCoord[0].s;
    float it = gl_TexCoord[0].t;

    float brickColumn = floor(is*numTilesWidth - .0001);
    float brickRow = floor(it*numTilesHeight - .0001);
    float brickx = mod(is*numTilesWidth*tilewidth, tilewidth);
    float bricky = mod(it*numTilesHeight*tileheight, tileheight);
    
    float borderInfo = brickPattern[TwoDIndex(brickColumn, brickRow, numTilesWidth)];
    
    float vec3Noise = 1.0;
    
   
    vec3 finalColor;
    
    vec3 normDelta = vec3(0.0, 0.0, 1.0);

    if((borderInfo == 2.0 || borderInfo == 0.0 || brickx > mortarwidth) && (borderInfo == 1.0 || borderInfo == 0.0 || bricky > mortarwidth))
    {
       int colorID = brickColors[TwoDIndex(brickColumn, brickRow, numTilesWidth)];
        if(colorID == 1)
            finalColor = bc1;
        else if(colorID == 2)
            finalColor = bc2;
        else
            finalColor = bc3;

        float brickNoise = 2.0*noise1(gl_TexCoord[0].t) - 1.0; 
        finalColor += .5*finalColor*noise3(10.0*gl_TexCoord[0].st);

        normDelta = vec3(1.2*noise2(3.0*turbulence(gl_TexCoord[0].st, 6, 2.0, .8)*gl_TexCoord[0].st), 1.0) ;
    }
    else
    {
        finalColor = mortarcolor;
        
        if((borderInfo == 1.0 || borderInfo == 3.0) && brickx < mortarwidth)
        {
            normDelta = vec3(1.2*(-sqr(-brickx + sqrt(mortarwidth)) + mortarwidth),1.2*(-sqr(-brickx + sqrt(mortarwidth)) + mortarwidth) , 1.0);
        }
        else //in mortar on top
        {
            normDelta = vec3(1.2*(-sqr(-bricky + sqrt(mortarwidth)) + mortarwidth), 1.2*(-sqr(-bricky + sqrt(mortarwidth)) + mortarwidth), 1.0);
        } 
    }


    vec3 litColor = finalColor * max(dot(normDelta, LightDir), 0.0);
    vec3 reflectDir = reflect(LightDir, normDelta);
    
    float spec = max(dot(EyeDir, reflectDir), 0.0);
    spec = pow(spec, 6.0);
    spec *= SpecularFactor;
    spec = 0.0;
    litColor = min(litColor + spec, vec3(1.0));

    gl_FragColor = vec4(litColor, 1.0);

}
